/**
 * 按照rust官方文档说法，所有的指针指针都实现了Deref。 这个待确定
 * 本脚本测试常见的智能指针的Deref特质。
 * 
 * 可惜Cell,RefCell并么有实现Deref特质，所以不能直接使用。
 * 有直接实现的主要是Box，Rc,Arc,Ref,RefMut。
 * 
 */

use std::cell::{RefCell,Cell};
use std::borrow::BorrowMut;
use std::rc::Rc;
use std::cell::{Ref, RefMut};

#[derive(Debug,Clone)]
struct Family {
    father: String,
    mother: String,
    children: Vec<String>,
    addr: String,
    phone: String,
    year_income: u32,
}

fn main() {
    //1.0 测试Box指针。优点：直接使用，不要显式Deref.传参的时候&T，实际起到&（*T）的作用。
    test_box();

    //2.0 测试RefCell指针。优点：内部可变，需要使用borrow_mut(),borrow,take等。 但不能直接使用
    test_refcell();

    //3.0 测试Cell指针。优点：内部可变，但不安全，需要使用get_mut()，get!。 但不能直接使用
    test_cell();

    //4.0 测试Rc指针。优点：共享所有权，但不安全，需要使用clone!。 能直接使用
    test_rc();

    //5.0 测试Rc+Box的组合.优点：共享所有权，但不安全，需要使用clone!。 能直接使用
    //虽然进行了嵌套，但是rust会自动解开两层外壳
    test_rc_and_box();

}

fn test_box() {
    println!("测试Box指针------------------------------");
    let mut book_store = Box::new(vec!["三海经".to_string(), "论语".to_string(), "史记".to_string()]);
    println!("使用book_store[0]访问 {}", book_store[0]);
    book_store[0]="史记".to_string();
    let shj = book_store[0].clone() + " 作者：未知";
    println!("{}", shj);

    let mut lb = Box::new(Family {
        father: "杜甫".to_string(),
        mother: "杨氏".to_string(),
        children: vec!["杜宗文".to_string(), "杜宗武".to_string(),"风儿".to_string()],
        addr: "河南巩义".to_string(),
        phone: "".to_string(),
        year_income: 384448,
    });
    lb.addr="成都".to_string();
    lb.year_income=1738393;
    println!("丈夫:{},妻子:{},   家庭地址：{},家庭年收入:{}",lb.father, lb.mother, lb.addr, lb.year_income);
}

fn test_refcell() {
    println!("测试RefCell指针------------------------------");
    let family = RefCell::new(Family {
        father: "张三".to_string(),
        mother: "李四".to_string(),
        children: vec!["小明".to_string(), "小红".to_string()],
        addr: "北京朝阳区".to_string(),
        phone: "123456".to_string(),
        year_income: 360000,
    });

    let borrow_family = family.borrow();
    println!("家庭地址：{},家庭年收入:{}", borrow_family.addr, borrow_family.year_income);
}

fn test_cell(){
    println!("测试Cell指针------------------------------");
    let mut cell = Cell::new(10);
    println!("cell.get()={}", cell.get());
    cell.borrow_mut().set(20);
    let qty=cell.get_mut();
    *qty+=1;
    println!("cell.get()={}", cell.get());
}

fn test_rc(){
    println!("测试Rc指针------------------------------");
    let mut rc = Rc::new(Family {
        father: "李白".to_string(),
        mother: "许氏".to_string(),
        children: vec!["伯禽".to_string(), "颇黎".to_string()],
        addr: "安陆".to_string(),
        phone: "".to_string(),
        year_income: 4556666,
    });
    println!("丈夫:{},妻子:{},   家庭地址：{},家庭年收入:{}", 
       rc.father, rc.mother,
       rc.addr, rc.year_income);

    //使用get_mut或者make_mut方法，可以修改内部数据。
    //get_mut要求只有一个所有者，性能较高。而make_mut不要求只有一个所有者，性能较低。
    let mut mf=Rc::get_mut(&mut rc).unwrap();
    mf.addr="长安".to_string();  
    mf.year_income=12345678;
    //Rc::make_mut(&mut rc).addr="长安".to_string();
    println!("丈夫:{},妻子:{},   家庭地址：{},家庭年收入:{}",rc.father, rc.mother,
    rc.addr, rc.year_income);
}

fn test_rc_and_box(){
    println!("测试Rc和Box指针组合------------------------------");
    let rc = Rc::new(Box::new(Family {
        father: "李白".to_string(),
        mother: "许氏".to_string(),
        children: vec!["伯禽".to_string(), "颇黎".to_string()],
        addr: "安陆".to_string(),
        phone: "".to_string(),
        year_income: 4556666,
    }));
    //Rc::make_mut(&mut rc).addr 
    println!("丈夫:{},妻子:{},   家庭地址：{},家庭年收入:{}", rc.father, rc.mother,
    rc.addr, rc.year_income);      
}

#[allow(dead_code)]
fn  test_ref(){
    //测试RefMut,Ref特质。
    // RefMut,Ref特质是和Cell，RefCell配合使用的,所以不再写代码了！
}